using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Xml.Linq;
using EOS.Data;
using EOS.Data.Utils;
using EOS.OverviewSettings.Properties;

namespace EOS.OverviewSettings
{
    public class OverviewSettingsImporter
    {
        private readonly string _pathToXmlSettings;
        private readonly XDocument _doc;
        private EveOverview _eveOverview;
        private EosBase _db;

        private OverviewSettingsImporter(string pathToXmlSettings)
        {
            Contract.Requires(!String.IsNullOrEmpty(pathToXmlSettings), 
                "pathToXmlSettings may not be null or empty.");

            _pathToXmlSettings = pathToXmlSettings;
            _doc = XDocument.Load(pathToXmlSettings);
        }

        /// <summary>
        /// 
        /// </summary>
        public static EveOverview ImportOverviewXml(string pathToXmlSettings)
        {
            var overviewSettingsImporter = new OverviewSettingsImporter(pathToXmlSettings);

            overviewSettingsImporter.ParseOverviewXml();

            return overviewSettingsImporter._eveOverview;
        }

        private void ParseOverviewXml()
        {
            var globalSettingsElement = _doc.Root.Element("globalSettings");

            bool applyOnlyToShips = Convert.ToBoolean(globalSettingsElement.Element("applyOnlyToShips").Attribute("value").Value);
            bool hideCorpTicker = Convert.ToBoolean(globalSettingsElement.Element("hideCorpTicker").Attribute("value").Value);
            bool overviewBroadcastsToTop = Convert.ToBoolean(globalSettingsElement.Element("overviewBroadcastsToTop").Attribute("value").Value);
            bool useSmallColorTags = Convert.ToBoolean(globalSettingsElement.Element("useSmallColorTags").Attribute("value").Value);

            _eveOverview = new EveOverview
            {
                ApplyOnlyToShips = applyOnlyToShips,
                HideCorpTicker = hideCorpTicker,
                OverviewBroadcastsToTop = overviewBroadcastsToTop,
                UseSmallColorTags = useSmallColorTags
            };

            var connectionPool = new SqlceConnectionPool(Settings.Default.DBCnnString);
            using (_db = new EosBase(connectionPool.Connection))
            {
                FillOverviewProfiles();
                FillColumns(globalSettingsElement);
                FillOverviewTabs();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void FillOverviewProfiles()
        {
            Contract.Requires(_doc != null);
            Contract.Requires(_doc.Root != null);
            
            IEnumerable<XElement> profileElements = _doc.Root.Elements("profile");

            foreach (var element in profileElements)
            {
                var profile = new OverviewProfile(element.Attribute("name").Value, 
                                                  GetOverviewGroups(element),
                                                  GetFilteredStates(element));
                _eveOverview.OverviewProfiles.Add(profile);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private IList<OverviewGroup> GetOverviewGroups(XElement element)
        {
            Contract.Requires(element != null);

            IEnumerable<XElement> groupElements = element.Element("groups").Elements("group");
            IList<OverviewGroup> overviewGroups = new List<OverviewGroup>();

            foreach (var groupElement in groupElements)
            {
                int id = Convert.ToInt32(groupElement.Attribute("id").Value);
                var group = _db.OverviewGroups.Single(g => g.Id == id);
                overviewGroups.Add(group);    
            }

            return overviewGroups;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private IList<OverviewState> GetFilteredStates(XElement element)
        {
            

            Contract.Requires(element != null);

            IEnumerable<XElement> stateElements = element.Element("filteredStates").Elements("state");
            IList<OverviewState> filteredStates = new List<OverviewState>();

            // TODO: fill states table before use

            //foreach (var stateElement in stateElements)
            //{
            //    int state = Convert.ToInt32(stateElement.Attribute("state").Value);
            //    var overviewState = _db.OverviewStates.Single(s => s.Id == state);
            //    filteredStates.Add(overviewState);
            //}

            return filteredStates;
        }

        /// <summary>
        /// 
        /// </summary>
        private void FillOverviewTabs()
        {
            Contract.Requires(_doc != null);
            Contract.Requires(_doc.Root != null);

            IEnumerable<XElement> tabElements = _doc.Root.Elements("tab");
            
            foreach (var element in tabElements)
            {
                bool? showAll = element.Attribute("showAll") == null
                                   ? (bool?) null
                                   : Convert.ToBoolean(element.Attribute("showAll").Value);

                bool? showNone = element.Attribute("showNone") == null
                                   ? (bool?)null
                                   : Convert.ToBoolean(element.Attribute("showNone").Value);

                bool? showSpecials = element.Attribute("showSpecials") == null
                                   ? (bool?)null
                                   : Convert.ToBoolean(element.Attribute("showSpecials").Value);


                var overviewTab = new OverviewTab
                               {
                                   Name = element.Attribute("name").Value,
                                   OverviewProfileName = element.Attribute("overview").Value,
                                   BracketProfileName = element.Attribute("bracket").Value,
                                   ShowAll = showAll,
                                   ShowNone = showNone,
                                   ShowSpecials = showSpecials
                               };

                _eveOverview.OverviewTabs.Add(overviewTab);
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="globalSettingsElement"></param>
        private void FillColumns(XElement globalSettingsElement)
        {
            Contract.Requires(globalSettingsElement != null);

            IEnumerable<XElement> columnElements 
                = globalSettingsElement.Element("columns").Elements("column");
            
            foreach (var element in columnElements)
            {
                string id = element.Attribute("id").Value;
                var overviewColumn = _db.OverviewColumns.Single(c => c.Id == id);
                _eveOverview.Columns.Add(overviewColumn);
            }
        }        
    }
}